package com.kly.user.chatterService;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.alibaba.nacos.api.config.annotation.NacosValue;
import com.fqgj.common.api.Response;
import com.fqgj.common.utils.CollectionUtils;
import com.fqgj.common.utils.StringUtils;
import com.fqgj.log.factory.LogFactory;
import com.fqgj.log.interfaces.Log;
import com.google.api.client.util.Lists;
import com.google.common.collect.Maps;
import com.google.common.eventbus.AsyncEventBus;
import com.kly.enums.ParameterTypeEnum;
import com.kly.service.MemberService;
import com.kly.user.constant.RedisKey;
import com.kly.user.db.dao.*;
import com.kly.user.db.dbo.ModelUserSendMsgNumDBO;
import com.kly.user.db.entity.*;
import com.kly.user.dto.UserConversationDto;
import com.kly.user.dto.UserConversationRecordDto;
import com.kly.user.dto.chatter.request.ChatListReq;
import com.kly.user.dto.chatter.request.ConversationOPReq;
import com.kly.user.dto.chatter.request.ConversationReq;
import com.kly.user.dto.chatter.response.*;
import com.kly.user.dto.rongCloud.RongCloudReqContent;
import com.kly.user.enums.AppEnum;
import com.kly.user.enums.ConversationOPTypeType;
import com.kly.user.enums.RememberTime;
import com.kly.user.eventbus.ActionEnum;
import com.kly.user.eventbus.Event;
import com.kly.user.service.UserConversationService;
import com.kly.user.utils.ImagePrefixUtils;
import com.kly.user.utils.RedisService;
import com.kly.user.utils.ServiceUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 保存聊天会话
 */
@Service("chatService")
public class ChatServiceImpl implements ChatService {

    private static Log logger = LogFactory.getLog(ChatServiceImpl.class);
    @Resource
    UserConversationDao userConversationDao;
    @Resource
    UserConversationChatterDao userConversationChatterDao;
    @Resource
    UserConversationGroupDao userConversationGroupDao;
    @Resource
    UserChatterMappingDao userChatterMappingDao;
    @Resource
    UserConversationService userConversationService;
    @NacosValue(value = "${default.user.chat.level:[{\"levelName\":\"0\",\"sortBy\":1,\"value\":0},{\"levelName\":\"1\",\"sortBy\":2,\"value\":5},{\"levelName\":\"2\",\"sortBy\":3,\"value\":15},{\"levelName\":\"3\",\"sortBy\":4,\"value\":30},{\"levelName\":\"4\",\"sortBy\":5,\"value\":60},{\"levelName\":\"5\",\"sortBy\":6,\"value\":100},{\"levelName\":\"6\",\"sortBy\":7,\"value\":150},{\"levelName\":\"7\",\"sortBy\":8,\"value\":220},{\"levelName\":\"8\",\"sortBy\":9,\"value\":300},{\"levelName\":\"9\",\"sortBy\":10,\"value\":400},{\"levelName\":\"10\",\"sortBy\":11,\"value\":999999}]}", autoRefreshed = true)
    private String defaultUserChatLevelConfig;
    @NacosValue(value = "${chat.conversation.flag:1}", autoRefreshed = true)
    private Integer chatConversationFlag;
    @Resource
    UserMsgUnreadNumDao userMsgUnreadNumDao;
    @Resource
    UserConversationCustomerDao userConversationCustomerDao;
    @Resource
    UserMsgSendTotalDao userMsgSendTotalDao;
    @Resource
    MemberService memberService;
    @Resource
    UserMsgForChatterDao userMsgForChatterDao;
    @Resource
    RedisService redisService;
    @Resource
    UserWlmDao userWlmDao;

    @Resource
    UserDao userDao;

    /**
     * 会话类型：1-单聊会话, 2-群组会话, 3-超级群会话 3-聊天室会话, 4-系统会话
     */
    private static final Integer conversationType = 1;
    /**
     * 1、进入会话 2、离开会话
     */
    private static final Integer openChat = 1;

    private final static Integer TO_TOPPING = 1;
    private final static Integer TO_CANCEL_TOPPING = 0;
    private final static Integer TO_SAVE_CHAT = 1;
    private final static Integer TO_CANCEL_CHAT = 0;
    @Resource
    AsyncEventBus asyncEventBus;

    @Override
    public Response addConversation(ConversationOPReq req) {


        // 获取会话记录
        UserConversationEntity conversation = userConversationDao.queryConversation(req);
        ConversationOPTypeType opTypeType = ConversationOPTypeType.fromType(req.getOpType());
        if (Objects.isNull(opTypeType)) {
            return Response.error("The parameter[opType] is Illegal");
        }

        if (Objects.isNull(conversation)) {
            conversation = new UserConversationEntity();
            conversation.setUserCode(req.getUserCodeFriend());
            conversation.setUserCodeFriend(req.getModelUserCode());
            conversation.setTargetId(req.getModelUserCode());
            conversation.setConversationType(req.getConversationType());
            conversation.setStatus(1);
            if (ConversationOPTypeType.SAVE_CHAT == opTypeType) {

                UserConversationGroupEntity entity = new UserConversationGroupEntity();
                entity.setUserCodeFriend(req.getUserCodeFriend());
                entity.setModelUserCode(req.getModelUserCode());
                entity.setChatterUserCode(req.getChatterUserCode());
                entity.setGroupId(req.getUserGroupLabel());
                entity.setStatus(TO_SAVE_CHAT);
                List<UserChatterMappingEntity> userChatterMappingEntities = userChatterMappingDao.queryByModelUserCode(req.getModelUserCode());
                if (CollUtil.isNotEmpty(userChatterMappingEntities)) {
                    entity.setChatterUserCode(userChatterMappingEntities.get(0).getChatterUserCode());
                }
                userConversationGroupDao.insert(entity);
            }
        }

        switch (opTypeType) {
            case TOPPING:
                conversation.setToppingFlag(TO_TOPPING);
                break;
            case SAVE_CHAT:
                conversation.setGroupId(req.getUserGroupLabel());
                addOrRemoveFromGroup(req, TO_SAVE_CHAT);
                break;
            case CANCEL_TOPPING:
                conversation.setToppingFlag(TO_CANCEL_TOPPING);
                break;
            case CANCEL_SAVE_CHAT:
                addOrRemoveFromGroup(req, TO_CANCEL_CHAT);
                break;
            default:
                break;
        }

        if (opTypeType.getType() == ConversationOPTypeType.REMOVE_CHAT.getType()) {
            userConversationDao.removeChat(conversation.getUserCode(), conversation.getUserCodeFriend());
            userConversationDao.removeChat(conversation.getUserCodeFriend(), conversation.getUserCode());
            // 删除未读消息
            readMsg(conversation.getUserCode(), conversation.getUserCodeFriend(), conversation.getChatterUserCode());
        } else {
            if (opTypeType.getType() == ConversationOPTypeType.TOPPING.getType()) {
                List<String> userCodeFriend = userConversationDao.queryUserCodeFriend(req.getModelUserCode());
                if (userCodeFriend.size() > 9) {
                    return Response.error("Topping failed, add up to 10 topping chats");
                }
            } else {
                conversation.setLatestTime(new Date());
            }
            userConversationDao.saveOrUpdate(conversation);
            userConversationChatterDao.saveOrUpdate(conversation);
        }


        return Response.ok();
    }

    @Resource
    UserMsgDao userMsgDao;

    @Override
    public Response storageConversation(ConversationReq req) {

        // 查询chatterUserCode
        String chatterUserCode = getChatterUserCode(req);
        // 获取modelUserCode
        String modelUserCode = null;
        if (req.getSource().equals(AppEnum.MEBOO.getAppCode())) {
            modelUserCode = req.getToUserCode();
        } else if (req.getSource().equals(AppEnum.MECHAT.getAppCode())) {
            modelUserCode = req.getFromUserCode();
        }

        if (openChat.equals(req.getType())) {
            openChat(req, chatterUserCode, modelUserCode);
            return Response.ok();
        }
        updateLeaveTime2(req.getFromUserCode(), req.getToUserCode(), req.getLatestMsg());
        addChatterConversation(chatterUserCode, req.getToUserCode(), req.getFromUserCode(), modelUserCode, req.getLatestMsg(), req.getSessionId());
        return Response.ok();

    }

    /**
     * mechat进入或离开会话，都需要刷新当前用户的未读消息数
     */
    private void pushMsgToMechat(ConversationReq req, String chatterUserCode, String modelUserCode) {
        Map<String, Object> params = new HashMap<>();
        params.put("type", ParameterTypeEnum.MESSAGE_FEEDBACK.getId());
        params.put("bizCode", "M20004");
        params.put("userCode", req.getToUserCode());
        params.put("modelUserCode", modelUserCode);
        params.put("latestMsg", req.getLatestMsg());
        params.put("latestTime", getLatestDateTime(req));
        Event event = Event.builder().eventActionEnum(ActionEnum.PUSH_MSG).app(AppEnum.MECHAT).fromUserCode(req.getToUserCode())
                .toUserCode(chatterUserCode).content(com.alibaba.fastjson.JSONObject.toJSONString(params)).build();
        asyncEventBus.post(event);
    }

    private String getLatestDateTime(ConversationReq req) {
        final Date latestSendTime = req.getLatestTime();
        String dateTime = "";
        if (latestSendTime != null) {
            // 判断日期是否为当天
            if (DateUtil.isSameDay(latestSendTime, DateUtil.date())) {
                // 转为年月日格式
                dateTime = DateUtil.format(latestSendTime, "HH:mm");
            } else {
                // 判断日期是否为当年
                if (DateUtil.year(latestSendTime) == DateUtil.year(DateUtil.date())) {
                    // 转为月日格式
                    dateTime = DateUtil.format(latestSendTime, "MM-dd");
                } else {
                    // 转为年月日格式
                    dateTime = DateUtil.formatDate(latestSendTime);
                }
            }
        }
        return dateTime;
    }


    @Override
    public void updateUserLeaveTime(ConversationReq req) {
        updateEnterAndLeaveTime(req.getFromUserCode(), req.getToUserCode(), req.getType());
    }

    @Override
    public Response<ChatListDto> chatList(String chatterUserCode, String modelUserCode, Integer sessionSaveFlag) {

        // 查询会话列表
        final List<UserConversationCustomerEntity> chatSessions = userConversationCustomerDao.queryChatList(chatterUserCode, modelUserCode, sessionSaveFlag, 1, 500);
        if (CollectionUtils.isEmpty(chatSessions)) {
            return Response.ok();
        }

        // 查询用户发送数量
        final Map<String, List<UserMsgForChatterEntity>> userConversationMsgNum = getUserSendMsgNum(chatterUserCode, modelUserCode);


//        List<String> userCodeList = chatSessions.stream().map(UserConversationCustomerEntity::getUserCode).collect(Collectors.toList());

        // 查询用户发送数量
//        Map<String, UserConversationRecordDto> userConversationMsgNum = getStringUserConversationRecordDtoMap(modelUserCode, userCodeList);

        // chat列表
        final List<UserAccount> userAccounts = chatSessions.stream().map(o -> {
            final UserAccount userAccount = UserAccount.builder().build();
            BeanUtils.copyProperties(o, userAccount);
            getAndSetLevel(modelUserCode, userConversationMsgNum, userAccount);
            if (StringUtils.isEmpty(o.getLatestMsg())
                    || !o.getLatestMsg().startsWith("{") || !o.getLatestMsg().endsWith("}")) {
                userAccount.setLatestMsg(o.getLatestMsg());
            } else {
                String latestMsg = o.getLatestMsg();
                String content = null;
                if (JSONUtil.isTypeJSON(latestMsg)) {
                    RongCloudReqContent rongCloudReqContent = JSONUtil.toBean(latestMsg, RongCloudReqContent.class);
                    String extra = rongCloudReqContent.getExtra();
                    content = rongCloudReqContent.getContent();
                    logger.info("content: {},extra: {}", JSONUtil.parseObj(rongCloudReqContent), extra);
                    if (extra != null) {
                        extra = extra.replaceAll("=", ":");
                        JSONObject jsonObject = JSONUtil.parseObj(extra);
                        boolean isPrivate = jsonObject.get("isPrivate") != null &&
                                Boolean.TRUE.toString().equals(jsonObject.getStr("isPrivate"));
                        if (StringUtils.isNotEmpty(rongCloudReqContent.getGifDataSize())
                                || StringUtils.isNotEmpty(rongCloudReqContent.getImageUri())) {
                            content = isPrivate ? "private photo" : "photo";
                        } else if (StringUtils.isNotEmpty(rongCloudReqContent.getSightUrl())) {
                            content = isPrivate ? "private video" : "video";
                        }
                    }
                } else {
                    content = latestMsg;
                }


                userAccount.setLatestMsg(content);
            }

            userAccount.setAvatarUrl(ImagePrefixUtils.getFullImageUrl(userAccount.getAvatarUrl()));
            return userAccount;

        }).collect(Collectors.toList());

        // 统计总的未读消息数
        final int totalUnReadNum = chatSessions.stream().mapToInt(UserConversationCustomerEntity::getUnReadNum).sum();

        return Response.ok(ChatListDto.builder().totalUnReadNum(totalUnReadNum).conversationChatList(userAccounts).build());

    }


    @Nullable
    private String getChatterUserCode(ConversationReq req) {
        String chatterUserCode = req.getChatterUserCode();
        if (org.springframework.util.StringUtils.isEmpty(chatterUserCode)) {
            final List<UserChatterMappingEntity> userChatterMappingEntities =
                    userChatterMappingDao.queryByModelUserCode(req.getFromUserCode(), req.getToUserCode());
            if (CollectionUtils.isNotEmpty(userChatterMappingEntities)) {
                chatterUserCode = userChatterMappingEntities.get(0).getChatterUserCode();
            }
        }
        return chatterUserCode;
    }

    @NotNull
    private Integer openChat(ConversationReq req, String chatterUserCode, String modelUserCode) {

        List<UserConversationEntity> fromUserConversation = userConversationDao.queryConversionByUserCode(
                req.getFromUserCode(), req.getToUserCode(), conversationType);
        if (CollectionUtils.isEmpty(fromUserConversation)) {
            // 添加会话
            addConversation(chatterUserCode, req.getFromUserCode(), req.getToUserCode(), modelUserCode, req.getLatestMsg(), req.getSessionId());
            // 添加到model组中
            addConversationGroup(chatterUserCode, req.getFromUserCode(), req.getToUserCode(), modelUserCode, req.getSource());
        } else {
            updateLeaveTime2(req.getFromUserCode(), req.getToUserCode(), req.getLatestMsg());
            addChatterConversation(chatterUserCode, req.getFromUserCode(), req.getToUserCode(), modelUserCode, req.getLatestMsg(), req.getSessionId());
        }

        List<UserConversationEntity> toUserConversation = userConversationDao.queryConversionByUserCode(
                req.getToUserCode(), req.getFromUserCode(), conversationType);
        if (CollectionUtils.isEmpty(toUserConversation)) {
            // 添加会话
            addConversation(chatterUserCode, req.getToUserCode(), req.getFromUserCode(), modelUserCode, req.getLatestMsg(), req.getSessionId());
        } else {
            updateLeaveTime2(req.getFromUserCode(), req.getToUserCode(), req.getLatestMsg());
            addChatterConversation(chatterUserCode, req.getToUserCode(), req.getFromUserCode(), modelUserCode, req.getLatestMsg(), req.getSessionId());
        }

        return 1;
    }

    private Integer updateLeaveTime2(String fromUserCode, String toUserCode, String latestMsg) {
        Map<String, Object> map = new HashMap<>();
        map.put("userCode", fromUserCode);
        map.put("userCodeFriend", toUserCode);
        map.put("leaveTime", new Date());
        if (StringUtils.isNotEmpty(latestMsg)) {
            map.put("latestMsg", latestMsg);
        }
        return userConversationDao.updateLeaveTime(map);
    }

    private Integer updateEnterAndLeaveTime(String fromUserCode, String toUserCode, int type) {
        Map<String, Object> map = new HashMap<>();
        map.put("userCode", fromUserCode);
        map.put("userCodeFriend", toUserCode);
        if (openChat == type) {
            map.put("enterTime", new Date());
        } else {
            map.put("userLeaveTime", new Date());
        }
        return userConversationDao.updateEnterAndLeaveTime(map);
    }


    private void addConversation(String chatterUserCode, String fromUserCode, String toUserCode, String modelUserCode, String latestMsg, String sessionId) {

        UserConversationEntity entity = new UserConversationEntity();
        entity.setUserCode(fromUserCode);
        entity.setTargetId(toUserCode);
        entity.setUserCodeFriend(toUserCode);
        // LeaveTime 在第一次会话时，设置为当前时间，离开聊天页面时进行更新，以保障未读消息数查询
        entity.setLeaveTime(new Date());
        entity.setChatterUserCode(chatterUserCode);
        entity.setConversationType(conversationType);
        entity.setGroupId(modelUserCode);
        entity.setSessionId(sessionId);
        if (StringUtils.isNotEmpty(latestMsg)) {
            entity.setStatus(null);
            entity.setLatestMsg(latestMsg);
            entity.setLatestTime(new Date());
        }

        userConversationDao.insert(entity);
        try {
            userConversationChatterDao.insertConversation(entity);
        } catch (Exception e) {
            logger.error("insertConversation error :{}", e.getMessage());
        }

    }

    private void addChatterConversation(String chatterUserCode, String fromUserCode, String toUserCode, String modelUserCode, String latestMsg, String sessionId) {

        UserConversationEntity entity = new UserConversationEntity();
        entity.setUserCode(fromUserCode);
        entity.setTargetId(toUserCode);
        entity.setUserCodeFriend(toUserCode);
        // LeaveTime 在第一次会话时，设置为当前时间，离开聊天页面时进行更新，以保障未读消息数查询
        entity.setLeaveTime(new Date());
        entity.setChatterUserCode(chatterUserCode);
        entity.setConversationType(conversationType);
        entity.setGroupId(modelUserCode);
        entity.setSessionId(sessionId);
        if (StringUtils.isNotEmpty(latestMsg)) {
            entity.setStatus(null);
            entity.setLatestMsg(latestMsg);
            entity.setLatestTime(new Date());
        }
        try {
            userConversationChatterDao.saveOrUpdate(entity);
        } catch (Exception e) {
            logger.error("insertConversation error :{}", e.getMessage());
        }

    }

    private void addConversationGroup(String chatterUserCode, String fromUserCode, String toUserCode, String modelUserCode, Integer source) {
        String userCode = null;
        if (source.equals(AppEnum.MEBOO.getAppCode())) {
            userCode = fromUserCode;
        } else if (source.equals(AppEnum.MECHAT.getAppCode())) {
            userCode = toUserCode;
        }

        final UserConversationGroupEntity conversationGroup = userConversationGroupDao
                .queryUserGroupByCode(chatterUserCode, modelUserCode, userCode);

        if (conversationGroup == null) {
            UserConversationGroupEntity entity1 = new UserConversationGroupEntity();
            entity1.setGroupId(modelUserCode);
            entity1.setChatterUserCode(chatterUserCode);
            entity1.setModelUserCode(modelUserCode);
            entity1.setUserCodeFriend(userCode);
            entity1.setStatus(0);
            List<UserChatterMappingEntity> userChatterMappingEntities = userChatterMappingDao.queryByModelUserCode(modelUserCode);
            if (CollUtil.isNotEmpty(userChatterMappingEntities)) {
                entity1.setChatterUserCode(userChatterMappingEntities.get(0).getChatterUserCode());
            }
            userConversationGroupDao.insert(entity1);
        }
    }


    private List<UserConversationEntity> queryConversionByUserCode(ConversationReq req) {
        Map<String, Object> params = Maps.newHashMap();
        params.put("userCode", req.getFromUserCode());
        params.put("targetId", req.getToUserCode());
        return userConversationDao.queryConversionByUserCode(params);
    }

    /**
     * api/chat/modelChatList mode分组消息
     *
     * @param chatterUserCode chatterCode
     * @param modelUserCode   modelCode
     * @param sessionSaveFlag 是否关注
     * @return
     */
    @Override
    public Response<ChatListDto> chatList(String chatterUserCode, String modelUserCode, Integer sessionSaveFlag, Integer pageNum, Integer pageSize) {

        // 查询会话列表
        final List<UserConversationCustomerEntity> chatSessions = userConversationCustomerDao.queryChatList(chatterUserCode, modelUserCode, sessionSaveFlag, pageNum, pageSize);
        if (CollectionUtils.isEmpty(chatSessions)) {
            return Response.ok();
        }

        // 查询用户发送数量
        final Map<String, List<UserMsgForChatterEntity>> userConversationMsgNum = getUserSendMsgNum(chatterUserCode, modelUserCode);

        // chat列表
        final List<UserAccount> userAccounts = chatSessions.stream().map(o -> {
            final UserAccount userAccount = UserAccount.builder().build();
            BeanUtils.copyProperties(o, userAccount);
            getAndSetLevel(modelUserCode, userConversationMsgNum, userAccount);
            if (StringUtils.isEmpty(o.getLatestMsg())
                    || !o.getLatestMsg().startsWith("{") || !o.getLatestMsg().endsWith("}")) {
                userAccount.setLatestMsg(o.getLatestMsg());
            } else {
                String latestMsg = o.getLatestMsg();
                String content;
                if (JSONUtil.isTypeJSON(latestMsg)) {
                    RongCloudReqContent rongCloudReqContent = JSONUtil.toBean(latestMsg, RongCloudReqContent.class);
                    String extra = rongCloudReqContent.getExtra();
                    content = rongCloudReqContent.getContent();
//                    logger.info("content: {},extra: {}", JSONUtil.parseObj(rongCloudReqContent), extra);
                    if (extra != null) {
                        extra = extra.replaceAll("=", ":");
                        JSONObject jsonObject = JSONUtil.parseObj(extra);
                        boolean isPrivate = false;
                        if (jsonObject.get("albumType") != null) {
                            int albumType = Integer.parseInt(jsonObject.getStr("albumType"));
                            if (albumType == 3) {
                                isPrivate = true;
                            }
                        } else {
                            isPrivate = jsonObject.get("isPrivate") != null &&
                                    Boolean.TRUE.toString().equals(jsonObject.getStr("isPrivate"));
                        }

                        if (StringUtils.isNotEmpty(rongCloudReqContent.getGifDataSize())
                                || StringUtils.isNotEmpty(rongCloudReqContent.getImageUri())) {
                            content = isPrivate ? "private photo" : "photo";
                        } else if (StringUtils.isNotEmpty(rongCloudReqContent.getSightUrl())) {
                            content = isPrivate ? "private video" : "video";
                        }
                    } else {
                        JSONObject jsonObject = JSONUtil.parseObj(latestMsg);
                        if (jsonObject.containsKey("put")) {
                            JSONObject childJson = JSONUtil.parseObj(jsonObject.getStr("put"));
                            if (childJson.containsKey("destructTime")) {
                                String destructTime = childJson.getStr("destructTime");
                                Date date = new Date();
                                long todayDateMillis = date.getTime();
                                if (todayDateMillis > (Long.parseLong(destructTime) + 1000 * 60 * 60)) {
                                    content = "This will remain a secret for eternity.";
                                } else if (childJson.containsKey("isPrivate")) {
                                    String isPrivate = childJson.getStr("isPrivate");
                                    content = isPrivate.equals("true") ? "private photo" : "photo";
                                }
                            }

                        }
                    }
                } else {
                    content = latestMsg;
                }


                userAccount.setLatestMsg(content);
                userAccount.setMember(memberService.ifMember(o.getUserCode()).getData());
            }

            userAccount.setAvatarUrl(ImagePrefixUtils.getFullImageUrl(userAccount.getAvatarUrl()));
            return userAccount;

        }).collect(Collectors.toList());

        // 统计总的未读消息数
        final int totalUnReadNum = chatSessions.stream().mapToInt(UserConversationCustomerEntity::getUnReadNum).sum();

        return Response.ok(ChatListDto.builder().totalUnReadNum(totalUnReadNum).conversationChatList(userAccounts).build());

    }

    @Override
    public Response<ChatListDto> chatList(ChatListReq chatListReq) {

        // 查询会话列表
        List<UserConversationCustomerEntity> chatSessions;
        if (chatConversationFlag == 1) {
            chatSessions = userConversationCustomerDao.queryChatList(chatListReq.getChatterUserCode(), chatListReq.getModelUserCode(), chatListReq.getNickName(), chatListReq.getSessionSaveFlag(), chatListReq.getPageNum(), chatListReq.getPageSize());
        } else {
            chatSessions = userConversationCustomerDao.queryChatterChatList(chatListReq.getChatterUserCode(), chatListReq.getModelUserCode(), chatListReq.getNickName(), chatListReq.getSessionSaveFlag(), chatListReq.getPageNum(), chatListReq.getPageSize());
        }

        if (CollectionUtils.isEmpty(chatSessions)) {
            return Response.ok();
        }

        // 查询用户发送数量
        final Map<String, List<UserMsgForChatterEntity>> userConversationMsgNum = getUserSendMsgNum(chatListReq.getChatterUserCode(), chatListReq.getModelUserCode());

        // chat列表
        final List<UserAccount> userAccounts = chatSessions.stream().map(o -> {
            final UserAccount userAccount = UserAccount.builder().build();
            BeanUtils.copyProperties(o, userAccount);
            getAndSetLevel(chatListReq.getModelUserCode(), userConversationMsgNum, userAccount);
            if (StringUtils.isEmpty(o.getLatestMsg())
                    || !o.getLatestMsg().startsWith("{") || !o.getLatestMsg().endsWith("}")) {
                userAccount.setLatestMsg(o.getLatestMsg());
            } else {
                String latestMsg = o.getLatestMsg();
                String content;
                if (JSONUtil.isTypeJSON(latestMsg)) {
                    RongCloudReqContent rongCloudReqContent = JSONUtil.toBean(latestMsg, RongCloudReqContent.class);
                    String extra = rongCloudReqContent.getExtra();
                    content = rongCloudReqContent.getContent();
                    logger.info("content: {},extra: {}", JSONUtil.parseObj(rongCloudReqContent), extra);
                    if (extra != null) {
                        extra = extra.replaceAll("=", ":");
                        JSONObject jsonObject = JSONUtil.parseObj(extra);
                        boolean isPrivate = false;
                        if (jsonObject.get("albumType") != null) {
                            int albumType = Integer.parseInt(jsonObject.getStr("albumType"));
                            if (albumType == 3) {
                                isPrivate = true;
                            }
                        } else {
                            isPrivate = jsonObject.get("isPrivate") != null &&
                                    Boolean.TRUE.toString().equals(jsonObject.getStr("isPrivate"));
                        }

                        if (StringUtils.isNotEmpty(rongCloudReqContent.getGifDataSize())
                                || StringUtils.isNotEmpty(rongCloudReqContent.getImageUri())) {
                            content = isPrivate ? "private photo" : "photo";
                        } else if (StringUtils.isNotEmpty(rongCloudReqContent.getSightUrl())) {
                            content = isPrivate ? "private video" : "video";
                        }
                    } else {
                        JSONObject jsonObject = JSONUtil.parseObj(latestMsg);
                        if (jsonObject.containsKey("put")) {
                            JSONObject childJson = JSONUtil.parseObj(jsonObject.getStr("put"));
                            if (childJson.containsKey("destructTime")) {
                                String destructTime = childJson.getStr("destructTime");
                                Date date = new Date();
                                long todayDateMillis = date.getTime();
                                if (todayDateMillis > (Long.parseLong(destructTime) + 1000 * 60 * 60)) {
                                    content = "This will remain a secret for eternity.";
                                } else if (childJson.containsKey("isPrivate")) {
                                    String isPrivate = childJson.getStr("isPrivate");
                                    content = isPrivate.equals("true") ? "private photo" : "photo";
                                }
                            }

                        }
                    }
                } else {
                    content = latestMsg;
                }


                userAccount.setLatestMsg(content);
                userAccount.setMember(memberService.ifMember(o.getUserCode()).getData());
            }

            userAccount.setAvatarUrl(ImagePrefixUtils.getFullImageUrl(userAccount.getAvatarUrl()));
            return userAccount;

        }).collect(Collectors.toList());

        // 统计总的未读消息数
        final int totalUnReadNum = chatSessions.stream().mapToInt(UserConversationCustomerEntity::getUnReadNum).sum();

        return Response.ok(ChatListDto.builder().totalUnReadNum(totalUnReadNum).conversationChatList(userAccounts).build());

    }

    private void getAndSetLevel(String modelUserCode, Map<String, List<UserMsgForChatterEntity>> userConversationMsgNum, UserAccount userAccount) {
        if (userConversationMsgNum != null && userConversationMsgNum.containsKey(userAccount.getUserCode())) {
            final List<UserMsgForChatterEntity> userMsgForChatterEntities = userConversationMsgNum.get(userAccount.getUserCode());
            if (CollectionUtils.isEmpty(userMsgForChatterEntities)) {
                userAccount.setMsgNum(0);
                userAccount.setLevel(new UserLevelHelper(0, defaultUserChatLevelConfig).getUserLevel());
            } else {
                final Integer msgNum = userMsgForChatterEntities.parallelStream().filter(o1 -> o1.getToUserCode().equals(modelUserCode)).map(UserMsgForChatterEntity::getMsgNum).findAny().orElse(0);
                userAccount.setMsgNum(msgNum);
                userAccount.setLevel(new UserLevelHelper(msgNum, defaultUserChatLevelConfig).getUserLevel());
            }
        }
    }

    @Override
    public Response<Integer> getChatLevel(String userCode, String modelUserCode) {

        final List<UserMsgSendTotalEntity> userMsgSendTotal = userMsgSendTotalDao.queryByUserCode(userCode, modelUserCode);
        if (CollectionUtils.isEmpty(userMsgSendTotal)) {
            return Response.ok(1);
        }
        UserMsgSendTotalEntity currentChat = userMsgSendTotal.get(0);
        final Integer msgNum = currentChat.getMsgNum();
        return Response.ok(new UserLevelHelper(msgNum, defaultUserChatLevelConfig).getUserLevel());
    }

    @Override
    public Response<ChatMsgReadDto> queryUnReadMessageNum(String userCode, String chatterUserCode, String modelUserCode) {
        final List<UserConversationCustomerEntity> chatSessions = userConversationCustomerDao
                .queryUnReadNum(userCode, chatterUserCode, modelUserCode);
        if (CollectionUtils.isEmpty(chatSessions)) {
            return Response.ok(ChatMsgReadDto.builder().userAccounts(null).totalUnReadNum(0).build());
        }

        final List<UserMessageReadDto> userMessageReadDtos = chatSessions.stream().map(o -> UserMessageReadDto.builder().userCode(o.getUserCode()).userCodeFriend(o.getTargetId()).unReadNum(o.getUnReadNum()).build()).collect(Collectors.toList());

        final int totalUnReadNum = chatSessions.stream().mapToInt(UserConversationCustomerEntity::getUnReadNum).sum();

        final ChatMsgReadDto chatMsgReadDto = ChatMsgReadDto.builder().userAccounts(userMessageReadDtos).totalUnReadNum(totalUnReadNum).build();

        return Response.ok(chatMsgReadDto);
    }

    private Map<String, List<UserMsgForChatterEntity>> getUserSendMsgNum(String chatterUserCode, String modelUserCode) {

        final List<UserMsgForChatterEntity> userMsgSendTotalEntities = userMsgForChatterDao.queryByUserCode(chatterUserCode, null, modelUserCode);
        if (CollectionUtils.isEmpty(userMsgSendTotalEntities)) {
            return null;
        }
        return userMsgSendTotalEntities.parallelStream().collect(Collectors.groupingBy(UserMsgForChatterEntity::getFromUserCode));
    }

    private Map<String, UserConversationRecordDto> getStringUserConversationRecordDtoMap(String modelUserCode, List<String> userCodeList) {
        Map<String, Object> params = ServiceUtils.getParams();
        params.put("toUserCode", modelUserCode);
        params.put("list", userCodeList);
        return userConversationService.getUserConversationMsgNum(params);
    }

    @Override
    public UserConversationDto queryConversation(ConversationOPReq req) {
        UserConversationEntity userConversationEntities = userConversationDao.queryConversation(req);
        UserConversationDto userConversation = new UserConversationDto();
        if (userConversationEntities != null) {
            BeanUtil.copyProperties(userConversationEntities, userConversation);
            return userConversation;
        }
        return null;
    }

    @Override
    public Response readMsg(String fromUserCode, String toUserCode, String chatterUserCode) {
        return Response.ok(userMsgUnreadNumDao.readMessage(fromUserCode, toUserCode));
    }


    @Override
    public Response<List<UserLevelDto>> listUserChatLevel(String chatterUserCode, String modelUserCode) {
        logger.info("===listUserChatLevel==开始：chatterUserCode:{}, modelUserCode:{}", chatterUserCode, modelUserCode);
        final long startTime = System.currentTimeMillis();
        if (StringUtils.isEmpty(chatterUserCode) || StringUtils.isEmpty(modelUserCode)) {
            return Response.ok();
        }


        List<ModelUserSendMsgNumDBO> modelUserSendMsgNumDBOS = userWlmDao.listOnlineUserChats(modelUserCode);
        logger.info("===listUserChatLevel==获取在线用户、消息条数costTime:{}", System.currentTimeMillis() - startTime);

        if (CollectionUtils.isEmpty(modelUserSendMsgNumDBOS)) {
            logger.error("===listUserChatLevel==获取在线用户个数:0");
            return Response.ok();
        }
        List<String> allOnlineUsers = modelUserSendMsgNumDBOS.stream().map(ModelUserSendMsgNumDBO::getUserCode).collect(Collectors.toList());

        Map<String, Object> params = Maps.newConcurrentMap();
        params.put("list", allOnlineUsers);
        List<UserEntity> userEntities = userDao.selectUsers(params);
        Map<String, UserEntity> map = new HashMap<>();
        userEntities.forEach(u -> {
            map.put(u.getUserCode(), u);
        });

        logger.info("===listUserChatLevel==获取在线用户个数:{}", modelUserSendMsgNumDBOS.size());

        List<UserLevelDto> userLevelDtos = Lists.newArrayList();
        for (ModelUserSendMsgNumDBO entity : modelUserSendMsgNumDBOS) {
            final Integer userLevel;
            try {
                userLevel = new UserLevelHelper(entity.getMsgNum(), defaultUserChatLevelConfig).getUserLevel();
                String avatarUrl = "";
                if (map.containsKey(entity.getUserCode())) {
                    avatarUrl = ImagePrefixUtils.getFullImageUrl(map.get(entity.getUserCode()).getAvatarUrl());
                }
                userLevelDtos.add(UserLevelDto.toDto(entity.getUserCode(), entity.getModelUserCode(), userLevel, map.get(entity.getUserCode()).getNickName(), avatarUrl));
            } catch (Exception e) {
                logger.error("===listUserChatLevelError==计算会话等级异常，userCode:{}, modelUserCode:{}", entity.getUserCode(), entity.getModelUserCode(), e);
            }
        }
        logger.info("===listUserChatLevel==获取在线用户、消息条数结束，costTime:{}", System.currentTimeMillis() - startTime);
        return Response.ok(userLevelDtos);
    }


    private void addOrRemoveFromGroup(ConversationOPReq req, int i) {
        UserConversationGroupEntity userConversationGroup = userConversationGroupDao.queryConversationGroup(req);
        userConversationGroup.setStatus(i);
        userConversationGroupDao.updateByPrimaryKey(userConversationGroup);
    }


}
